package com.yungu.swift.order.thread.socket;

import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.SpringContextHolder;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.order.dao.OrderMapper;
import com.yungu.swift.order.helper.OrderAssignHelper;
import com.yungu.swift.order.helper.OrderHelper;
import com.yungu.swift.order.helper.OrderPushHelper;
import com.yungu.swift.order.model.dto.OrderDetailDto;
import com.yungu.swift.order.model.dto.OrderDto;
import com.yungu.swift.order.service.OrderAssignService;
import com.yungu.swift.order.service.OrderDetailService;
import com.yungu.swift.socket.push.model.PushContent;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.utils.MapUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ScheduledFuture;

import static com.yungu.swift.constants.OrderConstant.ORDER_MAIN_STATUS_INITIAL;
import static com.yungu.swift.constants.OrderConstant.ORDER_STATUS_WAIT;
import static com.yungu.swift.order.service.impl.OrderAssignServiceImpl.scheduledFuturePool;

/**
 * 描述：循环推送订单
 * 五分钟内循环推送订单，40秒推送一次，直到订单被抢或者超出五分钟
 *
 * @author Zerrion
 * @Time 2018/12/27
 */
@Slf4j
public class CyclePushOrderThread implements Runnable {

    private PushService pushService;
    private OrderMapper orderMapper;
    private OrderDetailService orderDetailService;
    private RedisCacheService redisCacheService;
    /**
     * 推送的内容
     */
    private PushContent pushContent;
    /**
     * 订单实体
     */
    private OrderDto orderDto;
    /**
     * 订单详情实体
     */
    private OrderDetailDto orderDetailDto;
    private String carModelValuationUuid;
    private int pushDistance;

    /**
     * 构造函数
     *
     * @param orderDto
     */
    public CyclePushOrderThread(OrderDto orderDto, OrderDetailDto orderDetailDto, String carModelValuationUuid, Integer pushDistance) {
        this.pushService = SpringContextHolder.getBean(PushService.class);
        this.orderMapper = SpringContextHolder.getBean(OrderMapper.class);
        this.orderDetailService = SpringContextHolder.getBean(OrderDetailService.class);
        this.redisCacheService = SpringContextHolder.getBean(RedisCacheService.class);
        this.orderDto = orderDto;
        this.orderDetailDto = orderDetailDto;
        this.carModelValuationUuid = carModelValuationUuid;
        this.pushDistance = Optional.ofNullable(pushDistance).orElse(4000);
        //推送附加数据对象
        Map<String, Object> dataMap = OrderPushHelper.buildPushMap(orderDto, orderDetailDto);
        //封装推送的内容
        this.pushContent = PushContent.newInstance4Dri(orderDto.getAppid(), PushContent.ORDER_PUSH, dataMap);
    }

    @Override
    public void run() {
        if (null == orderDto) {
            return;
        }
        String originCityUuid = orderDetailDto.getOriginCityUuid();
        Double originLng = orderDetailDto.getOriginLng();
        Double originLat = orderDetailDto.getOriginLat();
        //订单推送次数
        Integer pushTime = 0;
        //是否火车站订单
        boolean isStationOrder = OrderHelper.isStationOrder(orderDetailDto);
        //推送集合模板，用来推送系统自动取消订单
        List<String> clientUuidList = new ArrayList<>();
        if (!canPush(orderDto.getUuid(), clientUuidList, pushTime)) {
            log.warn("orderUuid:{} 订单状态改变或已排到司机，执行线程取消逻辑", orderDto.getUuid());
            ScheduledFuture scheduledFuture = scheduledFuturePool.get(orderDto.getUuid());
            scheduledFuture.cancel(true);
            return;
        }
        //订单时效类型是实时单
        if (CommonConstant.TYPE_TIME_REAL_TIME == orderDto.getTypeTime()) {
            clientUuidList = OrderAssignHelper.filterGrabDriver(orderDto.getAppid(), orderDto.getTypeModule(), originLng,
                    originLat, carModelValuationUuid, pushDistance, 100, orderDto.getSeatNum(),
                    orderDetailDto.getOriginCityUuid(), isStationOrder);
            // 排除实时单被锁定的司机
            Object obj = redisCacheService.get(OrderAssignService.ASSIGN_DRIVER_LOCK);
            if (obj != null) {
                clientUuidList.removeAll((List<String>) obj);
            }
        }
        //订单时效类型是预约单
        else {
            //根据车型过滤
            clientUuidList = OrderAssignHelper.getTheSameCityDriverByCarType(orderDto.getAppid(), orderDto.getTypeModule(),
                    originCityUuid, carModelValuationUuid, orderDetailDto.getDeparTime(), 3,
                    orderDto.getSeatNum(), isStationOrder);
        }

        //推送新增订单给司机
        pushService.sendMessageByList(clientUuidList, pushContent);
        pushTime++;
        log.info("---推送订单号：{} 推送次数：{} 推送司机：{}", orderDto.getUuid(), pushTime, clientUuidList);
        //缓存本订单推送的司机
        redisCacheService.set("push" + orderDto.getUuid(), clientUuidList);
    }

    /**
     * 判断订单是否能推送（初始化，未被抢单，未取消或者关闭）
     *
     * @return boolean true:能推送订单  false：已过推送生命周期
     */
    private boolean canPush(String orderUuid, List<String> clientUuidList, Integer pushTime) {
        if (pushTime == 0) {
            return true;
        }
        Map<String, Object> params = MapUtils.build("uuid", orderUuid);
        log.info("开始推单---orderUuid:{}", orderUuid);
        OrderDto orderDto = orderMapper.list(params).get(0);
        Long currentTime = System.currentTimeMillis();
        if (null == orderDto.getMatchTime()) {
            return false;
        }
        Long matchTime = orderDto.getMatchTime().getTime();
        if (ORDER_STATUS_WAIT.equals(orderDto.getSubStatus()) && ORDER_MAIN_STATUS_INITIAL.equals(orderDto.getMainStatus())
                //订单是 初始化 状态，并且离订单创建时间未超过五分钟 因服务端与手机时间差 多增加10S
                && (currentTime - matchTime) < 310000) {
            return true;
        }
        if (ORDER_STATUS_WAIT.equals(orderDto.getSubStatus()) && ORDER_MAIN_STATUS_INITIAL.equals(orderDto.getMainStatus())) {
            OrderDto newOrderDto = new OrderDto();
            newOrderDto.setUuid(orderDto.getUuid());
            newOrderDto.setSubStatus(OrderConstant.ORDER_STATUS_NO_ANSWER);
            newOrderDto.setMainStatus(OrderConstant.ORDER_MAIN_STATUS_CANCEL);
            newOrderDto.setUpdateOn(new Date());
            orderMapper.edit(newOrderDto);
            orderDetailDto.setCancelTime(new Date());
            orderDetailDto.setCancelReason("5分钟未有司机接单自动取消");
            orderDetailService.saveOrUpdate(orderDetailDto);

            //系统自动取消 推送上次推送的所有司机
            Map<String, Object> dataMap = MapUtils.build();
            dataMap.put("orderUuid", orderDto.getUuid());
            dataMap.put("title", "订单已取消");
            dataMap.put("content", "订单超时，系统自动取消");
            dataMap.put("report", "订单超时，系统自动取消");
            dataMap.put("orderType", orderDto.getTypeModule());
            PushContent pushDriver = new PushContent(PushContent.To.DRIVER, orderDto.getAppid(), PushContent.ORDER_OVER_TIME_CANCEL, false, dataMap);
            log.info("--------无人接单，系统自动取消订单，推送司机：" + clientUuidList + "-------------------");
            pushService.sendMessageByList(clientUuidList, pushDriver);
        }
        return false;
    }
}
